using System;
using System.Collections;
using System.Data;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using DBRestriker.Data;
using DBRestriker.IO;
using System.ComponentModel;
using DBRestriker.Properties;
using System.Text;

namespace DBRestriker.Forms
{
	internal partial class MainForm : Form
	{
		private readonly Timer _keyDownTimer = new Timer();
		private readonly TableFilter _tableFilter = new TableFilter();

		private readonly IEnumerator _listSortDirectionEnumerator = Enum.GetValues(typeof(ListSortDirection)).GetEnumerator();

		public MainForm()
		{
			InitializeComponent();
			//InitializeTimer();
			InitializeMenu();
			
			// Write info text
			infoBox.AppendLine(MainFormBundle.SettingsInfo, Application.UserAppDataPath);
		}

		private void InitializeMenu()
		{
			searchModeToolStripComboBox.Items.AddRange(new SearchModeItem[]
       		{
       			new SearchModeItem(SearchMode.Instring, MainFormBundle.InstringSearchModeText), 
				new SearchModeItem(SearchMode.Prefix, MainFormBundle.PrefixSearchModeText)
       		});
			searchModeToolStripComboBox.SelectedIndex = 0;
		}

		private void InitializeTimer()
		{
			_keyDownTimer.Interval = 500;
			_keyDownTimer.Tick += TickEventHandler;
		}

		private void InitializeView()
		{
			WorkspaceManager workspaceManager = new WorkspaceManager();
			FileInfo excelFileInfo = workspaceManager.ExcelFileInfo;
			if (excelFileInfo != null)
			{
				ExcelReader excelReader = new ExcelReader(excelFileInfo.FullName);
				DataTable dataTable = excelReader.GetDataTable(1);
				if (dataTable != null)
				{
					bindingSource.DataSource = dataTable;
					dataView.DataSource = bindingSource;

					DataGridViewRowCollection sourceRows = dataView.Rows;
					if (0 < sourceRows.Count)
					{
						foreach (DataColumn sourceDataColumn in dataTable.Columns)
						{
							DataGridViewColumn filterColumn = new DataGridViewColumn(sourceRows[0].Cells[sourceDataColumn.ColumnName]);
							filterColumn.Name = sourceDataColumn.ColumnName;
							filterView.Columns.Add(filterColumn);
						}
						filterView.Rows.Insert(0, 1);

						dataView.ColumnHeadersVisible = true;
						dataView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
						dataView.ColumnHeadersVisible = false;
					}
				}
			}
		}

		private void ShowException(Exception exc)
		{
			MessageBox.Show(this, exc.Message, Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
			infoBox.AppendException(exc);
		}

		private void UpdateFilter()
		{
			DataGridViewRowCollection filterRows = filterView.Rows;
			if (0 < filterRows.Count)
			{
				SearchMode searchMode = default(SearchMode);
				SearchModeItem selectedItem = searchModeToolStripComboBox.SelectedItem as SearchModeItem;
				if (selectedItem != null)
				{
					searchMode = selectedItem.SearchMode;
				}
				string filterExpression = _tableFilter.GetFilterExpression(filterRows[0], searchMode);
				if (0 < filterExpression.Length)
				{
					try
					{
						infoBox.AppendLine(filterExpression);
						bindingSource.Filter = filterExpression;
					}
					catch (EvaluateException exc)
					{
						ShowException(exc);						
					}
					catch (SyntaxErrorException exc)
					{
						ShowException(exc);
					}
				}
				else
				{
					bindingSource.Filter = string.Empty;
				}
				infoBox.AppendLine(MainFormBundle.FilterResultFormat, dataView.RowCount);
			}
		}

		private void CellValueChangedEventHandler(object sender, DataGridViewCellEventArgs e)
		{
			if (sender.Equals(filterView))
			{
				UpdateFilter();
				//statusLabel.Text = MainFormBundle.DefaultStatusText;
				//if (_keyDownTimer.Enabled)
				//{
				//    _keyDownTimer.Stop();
				//}
				//else
				//{
				//    _keyDownTimer.Start();
				//}
			}
		}

		private void ClickEventHandler(object sender, EventArgs e)
		{
			if (sender.Equals(exportMenuItem))
			{
				foreach (DataGridViewRow selectedRow in dataView.SelectedRows)
				{
					StringBuilder lineBuilder = new StringBuilder();
					foreach (DataGridViewCell cell in selectedRow.Cells)
					{
						lineBuilder.AppendFormat("{0}{1}", (cell.Selected) ? cell.Value : string.Empty, Settings.Default.ColumnExportSeparator);
					}
					infoBox.AppendLine(lineBuilder.ToString());
				}
			}
			else if (sender.Equals(exitToolStripMenuItem))
			{
				Close();
			}
		}

		private void ColumnHeaderMouseClickEventHandler(object sender, DataGridViewCellMouseEventArgs e)
		{
			if (sender.Equals(filterView))
			{
				ListSortDirection direction = default(ListSortDirection);
				if (_listSortDirectionEnumerator.MoveNext())
				{
					direction = (ListSortDirection) _listSortDirectionEnumerator.Current;
				}
				else
				{
					_listSortDirectionEnumerator.Reset();
					if (_listSortDirectionEnumerator.MoveNext())
					{
						direction = (ListSortDirection) _listSortDirectionEnumerator.Current;
					}
				}
				dataView.Sort(dataView.Columns[e.ColumnIndex], direction);
				//dataView.Sort(_dataViewComparer);
			}
		}

		private void ColumnWidthChangedEventHandler(object sender, DataGridViewColumnEventArgs e)
		{
			DataGridViewColumn senderColumn = e.Column;
			int columnWidth = senderColumn.Width;
			int minColumnWidth = Settings.Default.ColumnWidthRange.Width;
			int maxColumnWidth = Settings.Default.ColumnWidthRange.Height;
			
			// Validate width
			if (columnWidth < minColumnWidth)
			{
				senderColumn.Width = minColumnWidth;
				return;
			}
			if (maxColumnWidth < columnWidth)
			{
				senderColumn.Width = maxColumnWidth;
				return;
			}

			// Modify corresponding column
			DataGridViewColumnCollection correspondingColumns = null;
			if (sender.Equals(filterView))
			{
				correspondingColumns = dataView.Columns;
			}
			else if (sender.Equals(dataView) && !IsAccessible)
			{
				correspondingColumns = filterView.Columns;
			}
			if (correspondingColumns != null)
			{
				DataGridViewColumn correspondingColumn = correspondingColumns[senderColumn.Name];
				if (correspondingColumn != null)
				{
					correspondingColumn.Width = senderColumn.Width;
				}
			}
		}

		private void CurrentCellChangedEventHandler(object sender, EventArgs e)
		{
			statusLabel.Text = MainFormBundle.WildcardHint;
		}

		private void FormClosingEventHandler(object sender, FormClosingEventArgs e)
		{
			if (WindowState == FormWindowState.Normal)
			{
				Settings.Default.MainFormSize = Size;
			}
			else
			{
				Settings.Default.MainFormSize = RestoreBounds.Size;
			}
			Settings.Default.Save();
		}

		private void LoadEventHandler(object sender, EventArgs e)
		{
			InitializeView();

			Size size = Settings.Default.MainFormSize;
			if (100 < size.Height + size.Width)
			{
				Size = size;
			}
		}

		private void KeyDownEventHandler(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Enter)
			{
				//if (_keyDownTimer.Enabled)
				//{
				//    _keyDownTimer.Stop();
				//}
				UpdateFilter();
			}
		}

		private void OpeningEventHandler(object sender, CancelEventArgs e)
		{
			if (sender.Equals(contextMenu))
			{
				exportMenuItem.Enabled = 0 < dataView.SelectedRows.Count;
			}
		}

		private void SelectedIndexChangedEventHandler(object sender, EventArgs e)
		{
			if (sender.Equals(searchModeToolStripComboBox))
			{
				Focus();
				UpdateFilter();
			}
		}

		private void TickEventHandler(object sender, EventArgs e)
		{
			UpdateFilter();
			_keyDownTimer.Stop();
		}
	}
}